package edzest.basic;

import java.util.ArrayList;

public class J22_Generic {

	public static void main(String[] args) {
		// 컬렉션 프레임워크를 구성하는 핵심 기술
		// 흔히, 타입매개변수라고 불리우는 <E>,<K>,<V> 등의
		// 다이아몬드 기호를 이용해서 컬렉션의 요소들을
		// [일반화]할 수 있음 
		// 이것을 통해 엄격한 자료형 검사도 할 수 있고
		// 불필요한 형변환도 방지할 수 있음
		
		J22_Tiger tiger = new J22_Tiger();
		J22_Lion lion = new J22_Lion();
		J22_Zibra zibra = new J22_Zibra();
		ArrayList zoo = new ArrayList();
		
		zoo.add(tiger);
		zoo.add(lion);
		zoo.add(zibra);
		
		// 제네릭없는 ArrayList는 전부
		// Object형으로 받음
		// tiger = zoo.get(0); -> 타이거형 = 오브젝트형
		// Type mismatch: cannot convert from 
		// Object to J22_Tiger
		tiger = (J22_Tiger)zoo.get(0);
		// 귀찮게도 형변환이 필요
		lion = (J22_Lion)zoo.get(1);
		zibra = (J22_Zibra)zoo.get(2);
		
		// 하지만, 아래의 문제가 발생할 수 있음!!
		// 즉, 컴파일 단계에서 엄격한 자료형 검사를 
		// 하지 않았기 때문에 실행시 오류가 표시됨
		// zibra = (J22_Zibra)zoo.get(0); 
		// 지브라형 = (지브라형)타이거형
		// 위코드는 문법적으로는 에러 안뜨나 컴파일 시 아래와 같은 에러발생
		// java.lang.ClassCastException: 
		// edzest.basic.J22_Tiger cannot be cast to 
		// edzest.basic.J22_Zibra
		
		/*------------------------------------*/
		// <E> : Element, 배열 요소의 자료형 의미
		ArrayList<J22_Tiger> cage1 = new ArrayList<J22_Tiger>();
		ArrayList<J22_Lion> cage2 = new ArrayList<J22_Lion>();
		ArrayList<J22_Zibra> cage3 = new ArrayList<>();
		// JDK7에서 추가 - 앞에서 <>지정하면 new부분 <>은 비워도 됨
		// ArrayList 에 타입 매개변수로 Tiger를 지정하면
		// 해당 ArrayList에는 Tiger형의 객체만 저장가능
		
		cage1.add(tiger);
		// cage1.add(lion);
		// The method add(J22_Tiger) in the type ArrayList<J22_Tiger> 
		// is not applicable for the arguments (J22_Lion)
		// cage1.add(zibra);
		tiger = cage1.get(0); 
		// 위에 제네릭 없을 때 처럼 캐스팅안해도 됨
		
		// lion = (lion)cage1.get(0);
		// 사자형 = (사자형)호랑이형
		// 문법상 자료형 불일치 오류 표시
		// 위에서는 문법상 에러 못잡아 냈는데 제네릭쓰니까 잡아냄
		// Type mismatch: cannot convert from J22_Tiger to J22_Lion
	}

}

class J22_Tiger {
	public void howl(){System.out.println("호랑이가 울어요");}
}
class J22_Lion {
	public void howl(){System.out.println("사자가 울어요");}
}
class J22_Zibra {
	public void howl(){System.out.println("얼룩말이 울어요");}
}